﻿using System.Security.Cryptography;
using System.Text;

namespace LDM.Framework;

/// <summary>
/// 加密操作
/// 说明：
/// 1. AES加密整理自支付宝SDK
/// 2. RSA加密采用 https://github.com/stulzq/DotnetCore.RSA/blob/master/DotnetCore.RSA/RSAHelper.cs
/// </summary>
internal static class Encrypt
{

    #region Md5加密

    /// <summary>
    /// Md5加密，返回16位结果
    /// </summary>
    /// <param name="value">值</param>
    public static string Md5By16(string value)
    {
        return Md5By16(value, Encoding.UTF8);
    }

    /// <summary>
    /// Md5加密，返回16位结果
    /// </summary>
    /// <param name="value">值</param>
    /// <param name="encoding">字符编码</param>
    public static string Md5By16(string value, Encoding encoding)
    {
        return Md5(value, encoding, 4, 8);
    }

    /// <summary>
    /// Md5加密
    /// </summary>
    private static string Md5(string value, Encoding encoding, int? startIndex, int? length)
    {
        if (string.IsNullOrWhiteSpace(value))
            return string.Empty;
        var md5 = new MD5CryptoServiceProvider();
        string result;
        try
        {
            var hash = md5.ComputeHash(encoding.GetBytes(value));
            result = startIndex == null ? BitConverter.ToString(hash) : BitConverter.ToString(hash, startIndex ?? default, length ?? default);
        }
        finally
        {
            md5.Clear();
        }
        return result.Replace("-", "");
    }

    /// <summary>
    /// Md5加密，返回32位结果
    /// </summary>
    /// <param name="value">值</param>
    public static string Md5By32(string value)
    {
        return Md5By32(value, Encoding.UTF8);
    }

    /// <summary>
    /// Md5加密，返回32位结果
    /// </summary>
    /// <param name="value">值</param>
    /// <param name="encoding">字符编码</param>
    public static string Md5By32(string value, Encoding encoding)
    {
        return Md5(value, encoding, null, null);
    }

    #endregion

    #region DES加密

    /// <summary>
    /// DES密钥,24位字符串
    /// </summary>
    public static string DesKey = "lQa9_&skzly%!9fs2@*UNA($ck_^:)'aI9e.^2Lbx9,5lf!j+~Hz@^hakuJ^crOb";

    /// <summary>
    /// DES加密
    /// </summary>
    /// <param name="value">待加密的值</param>
    public static string DesEncrypt(object value)
    {
        return DesEncrypt(value, DesKey);
    }

    /// <summary>
    /// DES加密
    /// </summary>
    /// <param name="value">待加密的值</param>
    /// <param name="key">密钥,24位</param>
    public static string DesEncrypt(object value, string key)
    {
        return DesEncrypt(value, key, Encoding.UTF8);
    }

    /// <summary>
    /// DES加密
    /// </summary>
    /// <param name="value">待加密的值</param>
    /// <param name="key">密钥,24位</param>
    /// <param name="encoding">编码</param>
    public static string DesEncrypt(object value, string key, Encoding encoding)
    {
        string text = value?.ToString() ?? string.Empty;
        if (ValidateDes(text, key) == false)
            return string.Empty;
        using (var transform = CreateDesProvider(key).CreateEncryptor())
        {
            return GetEncryptResult(text, encoding, transform);
        }
    }

    /// <summary>
    /// 验证Des加密参数
    /// </summary>
    private static bool ValidateDes(string text, string key)
    {
        if (string.IsNullOrWhiteSpace(text) || string.IsNullOrWhiteSpace(key))
            return false;
        return key.Length % 8 == 0;
    }

    /// <summary>
    /// 创建Des加密服务提供程序
    /// </summary>
    private static TripleDESCryptoServiceProvider CreateDesProvider(string key)
    {
        MD5CryptoServiceProvider hashMD5 = new MD5CryptoServiceProvider();
        var tempKey = hashMD5.ComputeHash(Encoding.ASCII.GetBytes(key));
        return new TripleDESCryptoServiceProvider { Key = tempKey, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 };
    }

    /// <summary>
    /// 获取加密结果
    /// </summary>
    private static string GetEncryptResult(string value, Encoding encoding, ICryptoTransform transform)
    {
        var bytes = encoding.GetBytes(value);
        var result = transform.TransformFinalBlock(bytes, 0, bytes.Length);
        return System.Convert.ToBase64String(result);
    }

    /// <summary>
    /// DES解密
    /// </summary>
    /// <param name="value">加密后的值</param>
    public static string DesDecrypt(object value)
    {
        return DesDecrypt(value, DesKey);
    }

    /// <summary>
    /// DES解密
    /// </summary>
    /// <param name="value">加密后的值</param>
    /// <param name="key">密钥,24位</param>
    public static string DesDecrypt(object value, string key)
    {
        return DesDecrypt(value, key, Encoding.UTF8);
    }

    /// <summary>
    /// DES解密
    /// </summary>
    /// <param name="value">加密后的值</param>
    /// <param name="key">密钥,24位</param>
    /// <param name="encoding">编码</param>
    public static string DesDecrypt(object value, string key, Encoding encoding)
    {
        string text = value?.ToString() ?? string.Empty;
        if (!ValidateDes(text, key))
            return string.Empty;
        using (var transform = CreateDesProvider(key).CreateDecryptor())
        {
            return GetDecryptResult(text, encoding, transform);
        }
    }

    /// <summary>
    /// 获取解密结果
    /// </summary>
    private static string GetDecryptResult(string value, Encoding encoding, ICryptoTransform transform)
    {
        var bytes = System.Convert.FromBase64String(value);
        var result = transform.TransformFinalBlock(bytes, 0, bytes.Length);
        return encoding.GetString(result);
    }

    #endregion

}
